package mjc.tds;

import java.io.*;
import mjc.type.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import mjc.type.DTYPE;
import mjc.type.INFO;
import mjc.type.VAR;

public class TDS implements Serializable {
	
	private HashMap<String,INFO> infos;
	private TDS parent;
	private String nom;
	
	public TDS(TDS parent,String nom) {
		infos=new HashMap<String,INFO>();
		this.parent=parent;
		this.nom=nom;
	}
	
	public TDS(String nom) {
		infos=new HashMap<String,INFO>();
		this.parent=null;
		this.nom=nom;
	}
	
	public TDS(TDS parent,LinkedList<VAR> params,String nom) {
		this.parent=parent;
		this.infos=new HashMap<String,INFO>();
		this.mettreParams(params);
		this.nom=nom;
	}
	
	public boolean droitValide(String droits) {
		String[] str=droits.split(" ");
		if (str.length<=2 && str.length>0)
			return (str.length==1) || (str.length==2 && (!str[0].equals(str[1])));
		else {
			return false;
		}
	}
	
	public TDS getParent() {
		return parent;
	}
	
	public void setParent(TDS parent) {
		this.parent=parent;
	}
	
	public String getNom() {
		return this.nom;
	}
	
	public void setNom(String nom) {
		this.nom=nom;
	}
	
	public HashMap<String,INFO> getInfos() {
		return infos;
	}
	
	public void mettreParams(LinkedList<VAR> params) {
		Iterator<VAR> it= params.iterator();
		while(it.hasNext()) {
			INFO info=it.next();
			infos.put(info.getNom(), info);
		}
	}
	
	public TDS(String filename,String nom) {
		FileInputStream fichier;
		TDS tds=null;
		try {
			fichier = new FileInputStream(filename);
			ObjectInputStream ois = new ObjectInputStream(fichier);
		    tds= (TDS) ois.readObject();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.nom=nom;
		this.infos=tds.getInfos();
		this.parent=tds.getParent();
	}
	
	public INFO chercherLocalement(String n) {
		if (infos.get(n)!=null) {
			if (infos.get(n).getDefini())
				return infos.get(n);
			else return null;
		}
		else return null;
	}

	public INFO chercherGlobalement(String n) {
		INFO i = chercherLocalement(n);
		if (i == null) {
			if (parent != null)
				return parent.chercherGlobalement(n);
		}
		return i;
	}

	public void inserer(String n, INFO i) {
		infos.put(n, i);
	}	
	
	public void fusionner(TDS tds) {
		Iterator<String> itn=tds.infos.keySet().iterator();
		Iterator<INFO> iti=tds.infos.values().iterator();
		while(itn.hasNext())
			this.inserer(itn.next(),iti.next());
	}
	

	public void serialisationTDS(TDS tds,String filename) {
		FileOutputStream fichier;
		try {
			fichier = new FileOutputStream(filename);
			ObjectOutputStream oos = new ObjectOutputStream(fichier);
		      oos.writeObject(tds);
		      oos.flush();
		      oos.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public String getSignature(String classe,String nom,LinkedList<DTYPE> params) {
		String str=classe+"."+nom + "(";
		Iterator<DTYPE> it=params.iterator();
		if (it.hasNext()) {
			str+=it.next().getNom();
			while(it.hasNext()) {
				str+=","+it.next().getNom();
			}
		}
		return str+")";
	}
		
	public LinkedList<DTYPE> getTypeParams(LinkedList<VAR> params) {
		LinkedList<DTYPE> lst = new 	LinkedList<DTYPE>();
		Iterator<VAR> it=params.iterator();
		while(it.hasNext()) 
			lst.add(it.next().getType());
		return lst;
	}
	
	public DTYPE getTypeThis(){
		return this.parent.chercherLocalement(this.parent.nom).getType();
	}
	
	public DTYPE getTypeSuper(){
		return this.parent.parent.chercherLocalement(this.parent.parent.nom).getType();
	}
	
	public String toString() {
		String str="\n";
		Iterator<String> itn=infos.keySet().iterator();
		Iterator<INFO> iti=infos.values().iterator();
		while(itn.hasNext()) {
			str+="info "+itn.next()+" : "+iti.next().toString() + "\n";
		}
		str+="fin TDS";
		return str;
	}
	
	public String afficherParent() {
		return parent.toString();
	}
	
	public static void main(String[] args) {
		INFO i=new INFO("x",0,true,new DTYPE("int",1));
		INFO j=new INFO("y",1,true,new DTYPE("int",1));
		TDS tds=new TDS("toto");
		tds.inserer("x", i);
		tds.inserer("y", j);
		tds.serialisationTDS(tds, "mjc\\toto.tds");
	}
	
	public TDS getTDSType(DTYPE type) {
		return ((CLASSE)this.chercherGlobalement(type.getNom())).getTdsClasse();
	}
	
	public INFO rechercheTdsi(LinkedList<TDS>tdsi,String nom) {
		INFO i=null;
		Iterator<TDS> it = tdsi.iterator();
		while(it.hasNext() && i==null) {
			i=it.next().chercherGlobalement(nom);
		}
		return i;
	}
}
